<template>
  <div class="GlobalSearch-wrap">
    <div class="input-wrap">
      <div class="input-box">
        <div class="left">
          <el-popover width="298px" v-model="visible" popper-class="search-info-popover" :append-to-body="false"
            placement="bottom-start" trigger="click">
            <div class="info-box">
              <div class="head">
                <span>保存检索项</span>
                <el-link class="is-icon" @click="newSearch">新建检索项</el-link>
              </div>
              <ul v-if="conditionList.length" class="content">
                <el-tooltip v-for="(item, index) in conditionList" :key="index" :content="item.searchCondition"
                  effect="dark" placement="bottom">
                  <li>
                    <span class="name" @click="nameClick(item)">{{
                      item.alias
                      }}</span>
                    <span class="li-btn">
                      <el-tooltip effect="dark" content="编辑" placement="bottom">
                        <i class="vul-icon-edit" @click="editClick(item)"></i>
                      </el-tooltip>
                      <el-tooltip effect="dark" content="删除" placement="bottom">
                        <i class="vul-icon-delete" @click="deleteClick(item)"></i>
                      </el-tooltip>
                    </span>
                  </li>
                </el-tooltip>
              </ul>
              <div v-if="!conditionList.length" class="no-data">
                <i class="vul-icon-sensitive"></i>
                <span>暂无保存的检索项</span>
              </div>
            </div>
            <template v-slot:reference>
              <span class="btn">
                <i class="vul-icon-task"></i>
                <el-icon>
                  <ArrowDown />
                </el-icon>
              </span>
            </template>
          </el-popover>
        </div>
        <div class="right">
          <!-- <el-input
            ref="searchInput"
            v-model="searchInput"
            placeholder="请输入检索语句"
            clearable
            @clear="searchClick"
            @keyup.enter.native="searchClick"
          >
          </el-input> -->

          <el-autocomplete style="width: 100%" ref="searchInputs" class="inline-input" v-model="searchInput"
            :fetch-suggestions="querySearch" :popper-append-to-body="false" placeholder="请输入检索语句" clearable
            @clear="searchClick" @select="grammarSelect" @keyup.enter.native="searchClick">
            <template v-slot="{ item }">
              <div style="display: flex; justify-content: space-between" class="grammar-tip">
                <span style="width: 50%" class="value">{{ item.value }}</span>
                <span style="width: 50%" class="label">{{ item.label }}</span>
              </div>
            </template>
          </el-autocomplete>
        </div>
      </div>
      <div class="btn-box">
        <el-button type="primary" @click="searchClick">查询</el-button>
        <el-button type="info" @click="resetClick">重置</el-button>

        <el-tooltip class="item" effect="dark" content="添加过滤条件" placement="bottom">
          <div class="high-search" @click="showSearch">
            <i class="vul-icon-syntax"></i>
          </div>
        </el-tooltip>
        <el-tooltip class="item" effect="dark" content="资产导入" placement="bottom">
          <div class="high-search" @click="importClick">
            <i class="vul-icon-import"></i>
          </div>
        </el-tooltip>
      </div>
    </div>
    <!-- 筛选条件 -->

    <AdvancedGraph ref="advancedGraph" class="advanced-graph" :search-text="searchInput" :category="category"
      @advancedSearch="advancedSearch"></AdvancedGraph>
    <!-- 高级检索 -->
    <SearchPop v-if="showAdvancedSearchPop" :search-text="searchInput" :is-show.sync="showAdvancedSearchPop"
      :category="category" @advancedSearch="advancedSearch" @closeDia="closeDia"></SearchPop>
    <!-- 新建检索项 -->
    <el-dialog :title="dialogTitle" v-model="dialogVisible" :close-on-click-modal="false" :close-on-press-escape="false"
      :modal-append-to-body="false" width="640px" @closed="closed">
      <div class="dialog-body">
        <el-form ref="ruleFormRef" class="ruleForm" :model="ruleForm" :rules="rules" label-width="100px">
          <el-form-item label="名称：" prop="alias">
            <el-input v-model.trim="ruleForm.alias" size="small" placeholder="请输入名称(长度限制20字符)"
              maxlength="20"></el-input>
          </el-form-item>
          <el-form-item label="检索条件：" prop="searchCondition">
            <el-input v-model.trim="ruleForm.searchCondition" type="textarea" size="small"
              placeholder="请输入检索条件"></el-input>
          </el-form-item>
          <el-form-item label="描述：">
            <el-input v-model.trim="ruleForm.description" type="textarea" maxlength="100" show-word-limit></el-input>
          </el-form-item>
        </el-form>
      </div>
      <template v-slot:footer>
        <span class="dialog-footer">
          <el-button size="small" @click="cancel">取 消</el-button>
          <el-button type="primary" size="small" @click="submitForm(ruleFormRef)">保 存</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import {
  defineEmits,
  defineProps,
  onMounted,
  reactive,
  ref,
  Ref,
  watch,
} from 'vue';
import { matcherOpts } from '@/components/Expose/AdvancedSearch/common';
import AdvancedGraph from '@/components/Expose/AdvancedSearch/comps/AdvancedGraph.vue';
import SearchPop from '@/components/Expose/AdvancedSearch/comps/SearchPop.vue';
import { useStore } from 'vuex';
import type { FormInstance, FormRules } from 'element-plus';
import { ElMessage } from 'element-plus';
const store = useStore();
const emit = defineEmits(['searchClick', 'importClick']);
const props = defineProps({
  conditionVal: {
    type: String,
    default: '',
  },
  category: {
    type: String,
    default: '',
  },
});
interface RuleForm {
  id: string;
  scene: any;
  alias: string;
  searchCondition: string;
  description: string;
}

let rules = reactive<FormRules<RuleForm>>({
  alias: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  searchCondition: [
    { required: true, message: '请输入检索条件', trigger: 'blur' },
  ],
});
const ruleFormRef = ref<FormInstance>();
const searchInput = ref('');
const visible = ref(false);
const dialogVisible = ref(false);
const dialogTitle = ref('新建检索项');
let ruleForm = reactive<RuleForm>({
  id: '',
  scene: '', // 应用场景, 可不填;
  alias: '',
  searchCondition: '',
  description: '',
});
const showAdvancedSearchPop = ref(false);
let conditionList: Ref<RuleForm[]> = ref([]);
const grammarMap = ref([]);
const currentSelectProperty = ref<any>({});
const currentOperator = ref('');
const isGrammar = ref(false);
const defaultLogic = ref<any>(matcherOpts);
const defaultConnect = reactive([
  { value: '&&', label: '且' },
  { value: '||', label: '或' },
]);
const searchInputs = ref<any>(null);
watch(
  () => props.conditionVal,
  (newVal) => {
    searchInput.value = newVal;
  },
);

onMounted(() => {
  getCondition();
});
const closeDia = (val) => {
  showAdvancedSearchPop.value = val;
};
const closed = () => { };
const cancel = () => {
  dialogVisible.value = false;
};
// 判断语法是否是一个完整的JQL结构
const checkGrammar = (str) => {
  if (str) {
    if (str.trim().endsWith('"')) {
      return true;
    }

    for (const item of defaultLogic.value) {
      if (!str.trim().endsWith(item.value)) {
        currentOperator.value = 'property';
        return false;
      }
    }
  }
  return false;
};
const endsWithAny = (str) => {
  for (const item of defaultConnect) {
    if (str.trim().endsWith(item.value)) {
      return true;
    }
  }
  return false;
};
const advancedSearchOptss = async () => {
  await store.dispatch('expose/setAdvancedSearchOpts');
};
const querySearch = (queryString, cb) => {
  advancedSearchOptss()
    .then(() => {
      const advancedSearchOpts: any = store.state.expose.advancedSearchOpts;
      const grammarObj: any = {};
      if (
        typeof advancedSearchOpts === 'object' &&
        advancedSearchOpts !== null
      ) {
        const values = Object.values(advancedSearchOpts) as any[];
        values
          .reduce((acc, val) => acc.concat(val), [])
          .forEach((el: any) => {
            grammarObj[el.signValue] = el;
          });
      }
      const lastSpaceIndex = queryString.lastIndexOf(' ');
      const lastStr = queryString.slice(lastSpaceIndex + 1);
      let selectArr: any = [];
      for (const key in grammarObj) {
        selectArr.push({
          value: key,
          label: `搜索${grammarObj[key]['label']}`,
          el: grammarObj[key],
          operator: 'property', // 标记这是属性
        });
      }
      grammarMap.value = selectArr;
      if (queryString.trim() === '') {
        // 用户没有输入任何内容
        currentSelectProperty.value = {};
        currentOperator.value = 'property'; // 重置状态
      }
      // 判断值是否是一个完整JQL语句
      if (checkGrammar(searchInput.value)) {
        currentOperator.value = 'value';
        // 如果语句完整，且以连接符为结尾
        if (endsWithAny(searchInput.value)) {
          currentSelectProperty.value = {};
          currentOperator.value = 'property'; // 重置状态
        }
      } else {
        currentSelectProperty.value = {};
        if (searchInput.value) {
          defaultLogic.value.forEach((el) => {
            if (searchInput.value.trim().endsWith(el.value)) {
              currentOperator.value = 'logic';
            }
          });

          if (searchInput.value.trim().endsWith('")')) {
            currentOperator.value = 'value';
          }
        }
      }
      if (/\s$/.test(queryString)) {
        if (currentOperator.value === 'property') {
          if (currentSelectProperty.value?.propertyNameEn) {
            selectArr = currentSelectProperty.value?.propertyOperator?.map(
              (item) => ({
                value: item,
                operator: 'logic', // 标记这是逻辑符
              }),
            );
          } else if (!endsWithAny(searchInput.value)) {
            selectArr = defaultLogic.value?.map((item) => ({
              value: item.value,
              label: item.label,
              operator: 'logic', // 标记这是逻辑符
            }));
          }
        }
        // 输入完逻辑符该输入value
        else if (currentOperator.value === 'logic') {
          if (currentSelectProperty.value?.propertyNameEn) {
            selectArr = currentSelectProperty.value?.propertySelectValue?.map(
              (item) => ({
                ...item,
                operator: 'value', // 标记这是value
              }),
            );
          } else {
            selectArr = [];
          }
        }
        // 输入完value,形成一个完整的kv结构，提示输入连接符
        else if (currentOperator.value === 'value') {
          selectArr = defaultConnect?.map((item) => ({
            value: item.value,
            label: item.label,
            operator: 'connect', // 标记这是连接符
          }));
        }
      }

      const results = lastStr
        ? selectArr.filter(createFilter(lastStr))
        : selectArr;
      // 调用 callback 返回建议列表的数据
      cb(results);
    })
    .catch((error) => {
      // 处理可能出现的错误
      console.error('Error setting advancedSearchOpts:', error);
    });
};
const createFilter = (queryString) => {
  return (selectArr) => {
    return (
      selectArr.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
    );
  };
};
const grammarSelect = (item) => {
  const grammarValue = searchInputs.value.inputRef.input.value;
  const lastValue = item.operator === 'value' ? item.key : item.value; // 因为value值是一个map，传递的是key
  // 选中当前选择的属性对象
  if (item?.operator === 'property') {
    currentSelectProperty.value = { ...item };
  }
  // this.currentOperator = item.operator // 记录上一步选择的位置
  // 用选择的数据替换最后一个空格后面的输入的字符串
  const lastSpaceIndex = grammarValue.lastIndexOf(' ');
  searchInput.value =grammarValue.substring(0, lastSpaceIndex + 1) + lastValue + ' '; // 构建新的字符串
  searchInputs.value.blur()
  
};
const openPopover = () => {
  visible.value = true;
};
const getInputVal = () => {
  return searchInput.value;
};
const searchClick = () => {
  emit('searchClick', searchInput.value);
};
const resetClick = () => {
  searchInput.value = '';
  searchClick();
};
const showSearch = () => {
  showAdvancedSearchPop.value = true;
};
const importClick = () => {
  emit('importClick');
};


const newSearch = () => {
  if (!searchInput.value) {
    ElMessage.error('请输入检索语句');
    return;
  }
  dialogTitle.value = '新建检索项';
  dialogVisible.value = true;
  ruleForm.searchCondition = searchInput.value;
};
const advancedSearch = (searchText, flag) => {
  searchInput.value = searchText;
  searchClick();
};

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.validate(async (valid, fields) => {
    if (valid) {
      let res;
      if (dialogTitle.value === '新建检索项') {
        res = await store.dispatch('expose/addCondition', ruleForm);
      } else {
        res = await store.dispatch('expose/editCondition', ruleForm);
      }
      if (res.code !== 0) {
        return;
      }
      dialogVisible.value = false;
      getCondition();
      resetCondition();
    } else {
      return false;
    }
  });
};

const getCondition = async () => {
  const { code, data = {} } = await store.dispatch('expose/getCondition', {
    scene: '', // 场景
    alias: '', // 别名, 右模糊查询
    pageSize: 10000,
    pageNumber: 1,
  });
  if (code !== 0) {
    return;
  }
  conditionList.value = data.list;
};

const nameClick = (item) => {
  searchInput.value = item.searchCondition;
  searchClick();
};

const resetCondition = () => {
  dialogTitle.value = '新建检索项';
  ruleForm.id = '';
  ruleForm.scene = '';
  ruleForm.alias = '';
  ruleForm.searchCondition = '';
  ruleForm.description = '';
};

const editClick = (item: any) => {
  dialogVisible.value = true;
  dialogTitle.value = '编辑检索项';
  ruleForm = item;
};

const deleteClick = async (item) => {
  const { code } = await store.dispatch('expose/deleteCondition', {
    id: item.id,
  });
  if (code !== 0) {
    return;
  }
  await getCondition();
};
</script>
<style lang="scss" scoped>
.GlobalSearch-wrap {
  .input-wrap {
    display: flex;

    .input-box {
      flex: 1;
      display: flex;
      align-items: center;

      .left {
        width: 56px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px 0px 0px 4px;
        box-sizing: border-box;
        border: 1px solid rgb(220, 223, 230);
        // background: rgba(41, 45, 76, 0.5);
        // color: rgba(255, 255, 255, 0.8);
        cursor: pointer;

        .btn {
          display: flex;
          align-items: center;
          justify-content: center;
        }
      }

      .right {
        flex: 1;
        position: relative;

        .inline-input {
          width: 100%;

          .grammar-tip {
            display: flex;
            align-items: center;

            .value {
              width: 50%;
            }

            .label {
              width: 50%;
            }
          }
        }

        .select-wrap {
          width: 100%;
          position: absolute;
          top: 32px;
          left: 0px;
          z-index: 999;
          background: #191c34;
          box-sizing: border-box;
          border: 1px solid rgba(58, 125, 255, 0.3);
          box-shadow: 0px 10px 17px 0px rgba(0, 0, 0, 0.3);
          max-height: 285px;
          min-height: 100px;
          overflow-y: auto;

          >ul {
            li {
              display: flex;
              align-items: center;
              // justify-content: space-between;
              height: 30px;
              padding: 0px 15px;
              cursor: pointer;

              &:hover {
                background: #eee;
              }
            }
          }

          .no-data {
            height: 100px;
            color: rgba(255, 255, 255, 0.8);
            font-size: 14px;
            display: flex;
            align-items: center;
            justify-content: center;

            i {
              margin-right: 8px;
              color: #ffc100;
            }
          }
        }
      }
    }

    .btn-box {
      display: flex;
      align-items: center;
      margin-left: 8px;

      .el-button {
        border: none;
        font-family: PingFangSC-Regular;
        font-size: 14px;
        margin: 0px;
      }

      .el-button+.el-button {
        margin-left: 8px;
      }

      .high-search {
        width: 32px;
        height: 32px;
        border-radius: 4px;
        box-sizing: border-box;
        border: 1px solid rgba(0, 0, 0, 0.2);
        display: flex;
        align-items: center;
        justify-content: center;
        margin-left: 8px;
        cursor: pointer;

        &:hover {
          border: 1px solid #0289f7;

          i {
            color: #0289f7;
          }
        }

        i {
          font-size: 20px;
          // color: rgba(255, 255, 255, 0.8);
        }
      }
    }
  }
}
</style>
<style lang="scss">
.search-info-popover {
  width: 298px;

  .info-box {
    .head {
      @include flexBox($justifyContent: space-between);
      height: 54px;
      line-height: 54px;
      letter-spacing: 0em;
      // color: rgba(255, 255, 255, 0.9);
      // border-bottom: 1px solid rgba(255, 255, 255, 0.1);
      padding: 0px 16px;
    }

    .content {
      height: 210px;
      overflow-y: auto;

      >li {
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 30px;
        padding: 0px 15px;

        &:hover {
          background: #eee;

          .li-btn {
            display: block;
          }
        }

        .name {
          font-family: PingFangSC-Regular;
          font-size: 14px;
          // color: rgba(255, 255, 255, 0.9);
        }

        .li-btn {
          display: none;

          i {
            font-size: 16px;
          }

          .vul-icon-edit {
            color: #0289f7;
          }

          .vul-icon-delete {
            color: #ff4c4c;
            margin-left: 10px;
          }
        }
      }
    }

    .no-data {
      height: 210px;
      color: rgba(255, 255, 255, 0.8);
      font-size: 14px;
      display: flex;
      align-items: center;
      justify-content: center;

      i {
        margin-right: 8px;
        color: #ffc100;
      }
    }
  }
}
</style>
